import { ecs } from "./ECS";
import { ECSEntity } from "./ECSEntity";
import { ECSGroup } from "./ECSGroup";

export type CompType<T> = CompCtor<T> | number;

export interface EntityCtor<T>{
    new():T;
}
export interface CompCtor<T>{
    new():T
    tid:number;
    compName:string;
}
type CompAddOrRemove = (entity:ecs.Entity) =>void
export class ECSModel{
    /**实体自增id */
    static eid = 1;
    /**实体构造函数 */
    static entityCtors:Map<EntityCtor<any>,string> = new Map();
    /** 实体对象缓存池 */
    static entityPool:Map<string,ECSEntity[]> = new Map();
    /** 实体id查找实体对象  */
    static eid2Entity:Map<number,ECSEntity> = new Map();
    
    /**组件类型id */
    static compTid = 0;
    /**组件缓存池 */
    static compPools:Map<number,ecs.IComp[]> = new Map();
    /**组件构造函数，用于ecs.register注册时，记录不同类型的组件  */
    static compCtors:(CompCtor<any> | null)[]=[]
   /**
     * 每个组件的添加和删除的动作都要派送到“关心”它们的group上。goup对当前拥有或者之前（删除前）拥有该组件的实体进行组件规则判断。判断该实体是否满足group
     * 所期望的组件组合。
     */
    static compAddOrRemove:Map<number,CompAddOrRemove[]> = new Map();
     /** 编号获取组件 */
    static tid2comp:Map<number,ecs.IComp> = new Map();

    /**
     * 缓存的group
     * 
     * key是组件的筛选规则，一个筛选规则对应一个group
     */
    static groups:Map<number,ECSGroup> = new Map();
    /**
     * 创建group，每个group只关心对应组件的添加和删除
     * @param matcher 实体筛选器
     */
    static createGroup<E extends ECSEntity=ECSEntity>(matcher:ecs.IMatcher):ECSGroup<E>{
        let group  = ECSModel.groups.get(matcher.mid);
        if (!group) {
            group = new ECSGroup(matcher);
            ECSModel.groups.set(matcher.mid,group);
            let careComponentTypeIds = matcher.indices;
            for (let i = 0; i < careComponentTypeIds.length; i++) {
               ECSModel.compAddOrRemove.get(careComponentTypeIds[i])!.push(group.onComponentAddOrRemove.bind(group));
            }
        }
        return group as unknown as ECSGroup<E>;
    }

    static systems:Map<string,ecs.System> = new Map<string,ecs.System>();

}